package com.nicekun.calc;

import com.nicekun.calc.core.CalcBaseVisitor;
import com.nicekun.calc.core.CalcParser;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class EvalVisitor extends CalcBaseVisitor<BigDecimal> {
    private Map<String, BigDecimal> memory = new HashMap<>();

    @Override
    public BigDecimal visitId(CalcParser.IdContext ctx) {
        String id = ctx.ID().getText();
        if (memory.containsKey(id)) {
            return memory.get(id);
        }
        return Result.ONE;
    }

    //ID '=' expr NEWLINE # assign
    @Override
    public BigDecimal visitAssign(CalcParser.AssignContext ctx) {
        String id = ctx.ID().getText();
        BigDecimal v = visit(ctx.expr());
        memory.put(id, v);
        return v;
    }

    @Override
    public BigDecimal visitPrintExpr(CalcParser.PrintExprContext ctx) {
        BigDecimal v = visit(ctx.expr());
        System.out.println(ctx.expr().getText() + " => " + v);
        return BigDecimal.ZERO;
    }

    @Override
    public BigDecimal visitInt(CalcParser.IntContext ctx) {
        return BigDecimal.valueOf(Integer.parseInt(ctx.INT().getText()));
    }

    @Override
    public BigDecimal visitAddSub(CalcParser.AddSubContext ctx) {
        BigDecimal left = visit(ctx.expr(0));
        BigDecimal right = visit(ctx.expr(1));
        if (ctx.op.getType() == CalcParser.ADD) {
            return left.add(right);
        } else {
            return left.subtract(right);
        }
    }

    @Override
    public BigDecimal visitMulDiv(CalcParser.MulDivContext ctx) {
        BigDecimal left = visit(ctx.expr(0));
        BigDecimal right = visit(ctx.expr(1));
        if (ctx.op.getType() == CalcParser.MUL) {
            return left.multiply(right);
        } else {
            return left.divide(right);
        }
    }

    //'(' expr ')'
    @Override
    public BigDecimal visitParens(CalcParser.ParensContext ctx) {
        return visit(ctx.expr());
    }
}
